package org.lsj.kit.config.SpringSecurityImpl;

import org.lsj.kit.config.ApplicationContextProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.AccessDecisionManager;
import org.springframework.security.access.SecurityMetadataSource;
import org.springframework.security.access.intercept.AbstractSecurityInterceptor;
import org.springframework.security.access.intercept.InterceptorStatusToken;
import org.springframework.security.web.FilterInvocation;
import org.springframework.stereotype.Service;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

/**
 * Created by 豆腐干Sama on 2019/3/4.
 * 扩展AbstractSecurityInterceptor,将自定义的SecurityMetadataSource和AccessDecisionManager注入到父类中
 */
public class KitAbstractSecurityInterceptor extends AbstractSecurityInterceptor implements Filter{

    /**
     *这个过滤器会被添加两次，参考FilterSecurityInterceptor的invoke方法 避免重复调用
     * */
    static final String FILTER_APPLIED = "_spring_security_kit_security_int";
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        FilterInvocation fi = new FilterInvocation(servletRequest, servletResponse, filterChain);
        invoke(fi);
    }

    public void invoke(FilterInvocation fi) throws IOException,
            ServletException {
        if (fi.getRequest() != null
                && fi.getRequest().getAttribute(FILTER_APPLIED) != null) {
            fi.getChain().doFilter(fi.getRequest(),fi.getResponse());
        } else {
            if (fi.getRequest() != null) {
                fi.getRequest().setAttribute(FILTER_APPLIED, Boolean.TRUE);
            }
            InterceptorStatusToken token = super.beforeInvocation(fi);

            try {
                fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
            } finally {
                super.afterInvocation(token, null);
            }
            super.afterInvocation(token, null);
        }


    }

    /**
     * 实现obtainSecurityMetadataSource方法，通过SecurityMetadataSource获取到configuration attributes
     * */
    @Override
    public SecurityMetadataSource obtainSecurityMetadataSource() {
        KitSecurityMetadataSource bean = ApplicationContextProvider.getApplicationContext().getBean(KitSecurityMetadataSource.class);
        return bean;
    }

    /**
     * 将自定义的AccessDecisionManager赋值给父类,因为父类的beforeInvocation方法需要调用AccessDecisionManager.decide验证是否能够访问资源
     * accessDecisionManager.decide(authenticated, object, attributes);
     * */
    @Override
    public void setAccessDecisionManager(AccessDecisionManager accessDecisionManager) {
        super.setAccessDecisionManager(ApplicationContextProvider.getApplicationContext().getBean(KitAccessDecisionManager.class));
    }

    @Override
    public Class<?> getSecureObjectClass() {
        return FilterInvocation.class;
    }
}
